
#ifdef _WIN32
#include <windows.h>
#endif
#include <OTKXString.h>
#include <string>
#include <stdio.h>
#include <logger.h>
#include <iostream>
#include <sstream>

namespace gconvert
{
#ifdef _WIN32
    static int multi2uni(const std::string &multi, std::wstring &uni, UINT code)
    {
        auto len = MultiByteToWideChar(code, 0, multi.c_str(), -1, nullptr, 0);
        if (len <= 0)
        {
            LOG(LOG_ERROR) << __FILE__ << " : " << __LINE__ << " : " << GetLastError() << std::endl;
            return G_ERROR_INVALIDPARAM;
        }
        WCHAR *buf = new WCHAR[len];
        if (buf == nullptr)
        {
            LOG(LOG_ERROR) << __FILE__ << " : " << __LINE__ << " : "
                           << "can not new buf, size : " << len << std::endl;
            return G_ERROR_NOBUF;
        }
        len = MultiByteToWideChar(code, 0, multi.c_str(), -1, buf, len);
        uni.assign(buf);
        delete[] buf;
        buf = nullptr;
        return len;
    }

    static int uni2multi(const std::wstring &uni, std::string &multi, UINT code)
    {
        auto len = WideCharToMultiByte(code, 0, uni.c_str(), -1, nullptr, 0, nullptr, nullptr);
        if (len <= 0)
        {
            LOG(LOG_ERROR) << __FILE__ << " : " << __LINE__ << " : " << GetLastError() << std::endl;
            return G_ERROR_INVALIDPARAM;
        }
        CHAR *buf = new CHAR[len];
        if (buf == nullptr)
        {
            LOG(LOG_ERROR) << __FILE__ << " : " << __LINE__ << " : "
                           << "can not new buf, size : " << len << std::endl;
            return G_ERROR_NOBUF;
        }
        len = WideCharToMultiByte(code, 0, uni.c_str(), -1, buf, len, nullptr, nullptr);
        multi.assign(buf);
        delete[] buf;
        buf = nullptr;
        return len;
    }
#endif

    // ANSI->Unicode
    int ansi2uni(const std::string &ansi, std::wstring &uni)
    {
#ifdef _WIN32
        return multi2uni(ansi, uni, CP_ACP);
#endif
        return G_ERROR_SUCCEED;
    }

    // Unicode->ANSI
    int uni2ansi(const std::wstring &uni, std::string &ansi)
    {
#ifdef _WIN32
        return uni2multi(uni, ansi, CP_ACP);
#endif
        return G_ERROR_SUCCEED;
    }

    // UTF8->Unicode
    int utf82uni(const std::string &utf8, std::wstring &uni)
    {
#ifdef _WIN32
        return multi2uni(utf8, uni, CP_UTF8);
#endif
        return G_ERROR_SUCCEED;
    }

    // Unicode->UTF8
    int uni2utf8(const std::wstring &uni, std::string &utf8)
    {
#ifdef _WIN32
        return uni2multi(uni, utf8, CP_UTF8);
#endif
        return G_ERROR_SUCCEED;
    }

    // ANSI->UTF8
    int ansi2utf8(const std::string &ansi, std::string &utf8)
    {
        std::wstring uni;
        auto len = ansi2uni(ansi, uni);
        if (len <= 0)
        {
            return G_ERROR_INTERNAL;
        }
        return uni2utf8(uni, utf8);
    }

    // UTF8->ANSI
    int utf82ansi(const std::string &utf8, std::string &ansi)
    {
        std::wstring uni;
        auto len = utf82uni(utf8, uni);
        if (len <= 0)
        {
            return G_ERROR_INTERNAL;
        }
        return uni2ansi(uni, ansi);
    }
    // string->int
    int str2int(const std::string istr)
    {
        std::istringstream ss;
        ss.str(istr);
        int ret = 0;
        ss >> ret;
        return ret;
    }
    std::string GBKToUTF8(const char *strGBK)
    {
        int len = MultiByteToWideChar(CP_ACP, 0, strGBK, -1, NULL, 0);
        wchar_t *wstr = new wchar_t[len + 1];
        memset(wstr, 0, len + 1);
        MultiByteToWideChar(CP_ACP, 0, strGBK, -1, wstr, len);
        len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
        char *str = new char[len + 1];
        memset(str, 0, len + 1);
        WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
        std::string strTemp = str;
        if (wstr)
            delete[] wstr;
        if (str)
            delete[] str;
        return strTemp;
    }

    std::string UTF8ToGBK(const char *strUTF8)
    {
        int len = MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, NULL, 0);
        wchar_t *wszGBK = new wchar_t[len + 1];
        memset(wszGBK, 0, len * 2 + 2);
        MultiByteToWideChar(CP_UTF8, 0, strUTF8, -1, wszGBK, len);
        len = WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, NULL, 0, NULL, NULL);
        char *szGBK = new char[len + 1];
        memset(szGBK, 0, len + 1);
        WideCharToMultiByte(CP_ACP, 0, wszGBK, -1, szGBK, len, NULL, NULL);
        std::string strTemp(szGBK);
        if (wszGBK)
            delete[] wszGBK;
        if (szGBK)
            delete[] szGBK;
        return strTemp;
    }
} // namespace gconvert